package candao

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
)

//禅道api调用
type (
	CanDao struct {
		Build   string //测试单版本
		EndDate string //测试单截止日期

		Address  string
		Account  string
		Password string

		SessionId          string
		SessionExpiredDate int64    //session创建日期
		TaskHistory        []string //已经创建过测试的taskId集合

	}
)

func NewCanDao(address string, sessionId string) *CanDao {
	this := new(CanDao)
	this.Address = address
	this.SessionId = sessionId
	return this
}

//获取sessionId
func (this *CanDao) getSessionId() (sessionId string, err error) {
	var ack Session
	if err = this.httpGet("/api-getsessionid.json", &ack); err != nil {
		return
	}

	return ack.SessionID, nil
}

//登录
func (this *CanDao) Login() (err error) {

	var (
		res       Response
		sessionId string
	)

	//有效session
	if this.SessionId != "" && time.Now().Unix() <= this.SessionExpiredDate {
		return
	}

	if this.SessionId == "" {
		if sessionId, err = this.getSessionId(); err != nil {
			return
		}
	}

	resp, err := http.PostForm(fmt.Sprintf("%s/user-login.json?zentaosid=%s", this.Address, sessionId),
		url.Values{"account": {this.Account}, "password": {this.Password}})

	if err != nil {
		return err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	if err = json.Unmarshal(body, &res); err != nil {
		return
	}

	//登录成功
	if res.Status == "success" {
		this.SessionId = sessionId
		this.SessionExpiredDate = time.Now().Add(86400 * time.Second).Unix()
	}

	return

}

//获取某个任务的数据
func (this *CanDao) Task(taskId string) (task Task, err error) {
	var ack map[string]map[string]string

	err = this.httpPost(fmt.Sprintf("%s/task-view-%s.json?zentaosid=%s", this.Address, taskId, this.SessionId), nil, &ack)
	if strings.Contains(err.Error(), "map[string]string") {
		err = nil
	}
	//JsonPrint(ack)

	task.Id = taskId
	if err = Map2Struct(ack["task"], &task); err != nil {
		return
	}
	return

}

//创建测试单
func (this *CanDao) CreateTest(taskId string) (err error) {
	for _, v := range this.TaskHistory {
		if v == taskId {
			return
		}
	}

	if err = this.Login(); err != nil {
		return
	}

	if this.SessionId == "" {
		return errors.New("账号密码不能为空")
	}

	var task Task

	if task, err = this.Task(taskId); err != nil {
		return
	}

	if task.Name == "" {
		return
	}

	taskLink := fmt.Sprintf("%s/task-view-%s.html", this.Address, taskId)
	storyLink := fmt.Sprintf("%s/story-view-%s.html", this.Address, task.StoryID)

	desc := fmt.Sprintf(`<a href="%s" target="_blank">任务链接</a><br><a href="%s" target="_blank">需求链接</a>`, taskLink, storyLink)

	req := url.Values{
		"product": {"2"},
		"project": {"2"},
		"build":   {this.Build},
		"owner":   {"miaozhi"},
		"pri":     {"2"},
		"begin":   {time.Now().Format("2006-01-02")},
		"end":     {this.EndDate},
		"status":  {"wait"},
		"name":    {task.Name},
		"desc":    {desc},
	}

	if err = this.httpPost(fmt.Sprintf("%s/testtask-create-2.json?zentaosid=%s&t=json", this.Address, this.SessionId), req, nil); err != nil {
		return
	}

	this.TaskHistory = append(this.TaskHistory, taskId)

	return
}

//发送post
func (this *CanDao) httpPost(targetUrl string, req url.Values, ack interface{}) (err error) {
	var res Response

	resp, err := http.PostForm(targetUrl, req)
	if err != nil {
		return err
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		return err
	}
	fmt.Println(string(body))

	if len(body) > 0 && ack != nil {
		if err = json.Unmarshal(body, &res); err != nil {

		}
		if err = json.Unmarshal([]byte(res.Data), ack); err != nil {
			return err
		}
	}

	return
}

func (this *CanDao) httpGet(targetUrl string, ack interface{}) (err error) {
	var (
		content []byte
		res     Response
	)

	targetUrl = this.Address + targetUrl
	resp, err := http.Get(targetUrl)
	if err != nil {
		return
	}

	defer resp.Body.Close()

	content, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}

	if len(content) > 0 && ack != nil {
		err = json.Unmarshal(content, &res)

		if res.Data != "" {
			err = json.Unmarshal([]byte(res.Data), ack)
			//fmt.Println(res.Data)
		}

	}

	return

}

//json方式打印结构体
func JsonPrint(obj interface{}) {
	tmp, _ := json.MarshalIndent(obj, "", "     ")
	fmt.Println(string(tmp))
}

func Map2Struct(m interface{}, s interface{}) (err error) {
	var (
		content []byte
	)

	if m == nil || s == nil {
		return
	}

	if content, err = json.Marshal(m); err != nil {
		return
	}

	if err = json.Unmarshal(content, s); err != nil {
		return
	}

	return
}
